Instead of processing classes separately (which gives you the maximum freedom), there are occasions when you want to process bigger musical chunks. These are called motives.
A motive operates on a single, or multiple zone lists. A motive is a collection of classes:
symbol length velocity channel program controller duration groove tonality zone tuning
It may contain only one class, or multiple classes. Motive has a name and its definition follows an optional motive-tree inheritation. A motive can be operated as a whole, or applying symbol and vector processors to its classes. Finally motives are connected to sections and instruments.
This defines a motive tree which (if defined) is used for inheritance.
(def-motive-tree 'my-set
all (name1 group name2)
group (more1 more2 more3)
)
This defines now all motives to consist of same values.
(def-motive all
length '(1/16 1/8)
symbol '(a b c)
velocity '(10 20 30)
duration '(1/16. 1/8.)
)
Now you can define groups in motive tree to have different values.
(def-motive group
length '(1/4)
symbol '(d)
)
Now
(motive name1 symbol) ; and name2
--> (a b c)
(motive name1 velocity)
--> (10 20 30)
(motive more1 symbol) ; and more2, more3
--> (d)
(motive more1 velocity)
--> (10 20 30)
Motives defined in a tree are stored in atoms. Each atom in the motive tree will now contain a motive object .
more1
--> #<motive #x5A5D91>
Note: If necessary inheritation tree can be changed with inherit-motive.
(inherit-motive another-set)
Clearing values
To clear motive values in a tree from a given group use
(clear-motive-tree 'my-set 'group)
That will clear all motives and submotives etc found on 'group in motive-tree 'my-set.
Connection to Sections
Motives can connect to sections in two ways, by single class or as a whole.
Using Single Class
To connect a single class of a motive to a section class use list to build up zoned material, or use it directly. Motive is accesses with motive.
(motive more1 symbol) (a b c)
(motive more1 duration) (1/16. 1/8.)
(motive more1 program) nil
In def-section context the class can be omitted. Motive references withing a section sect-are written this way. Here each motive is a single zone motive. If motive contains multiple zones the results can be used as usual.
(def-section sect-a
piano
symbol (list (motive more1) ; each zone has its own material
(motive more2)
(motive more3))
bass
symbol (motive more1) ; goes through zones
synth
symbol (list (motive more1)) ; restarts at each zone
)
(same-as symbol of piano in sect-a) ((a b c) (a b c) (a b c))
(same-as symbol of bass in sect-a) (a b c)
(same-as symbol of synth in sect-a) ((a b c))
Using Whole Motives
Whole motives can be directly connected to sections using motive instead of class. It one motive is supplied, then motive output is a single list (..). If list is used, then each output is a double list ((..)). If there are multiple motives the output is a zone list ((..) (..) .. (..)).
(def-section sect-a
default
zone '(1/1)
piano1
motive name1 ; motive goes through zones
piano2
motive (list name1) ; motive restarts at each zone
piano3
motive (list more1 more2 more3) ; uses a motive in each zone
)
(same-as symbol of piano1 in sect-a) (a b c)
(same-as symbol of piano2 in sect-a) ((a b c))
(same-as symbol of piano3 in sect-a) ((a b c) (a b c) (a b c))
MultiZone Motives
A motive can as well has multiple zone material.
(def-motive multi
length '((1/16 1/8))
symbol '((a b c) (e f g))
velocity '(10 20 30)
duration '(1/16. 1/8.)
)
MultiZone motives can be connected in the same way as single zone motives, but since they already contain multiple zones, the result of the (list multi) will be the same as multi. In case of multiple motives (list multi multi multi) they are appended like with the ++ operation.
(def-section sect-a
piano1
motive multi
piano2
motive (list multi)
piano3
motive (list multi multi multi)
)
(same-as symbol of piano1 in sect-a) ((a b c) (e f g))
(same-as symbol of piano2 in sect-a) ((a b c) (e f g))
(same-as symbol of piano3 in sect-a) ((a b c) (e f g) (a b c) (e f g) (a b c) (e f g))
Motive Definition within Sections
Motives can also be defined directly within sections, and the motives become accessible for other instruments and motive operators.
(def-section sect-a
piano1
motive (def-motive theme
length '((1/16 1/8))
symbol '((a b c) (e f g))
velocity '(10 20 30)
duration '(1/16. 1/8.))
piano2
motive (rev theme)
piano3
motive (tran theme 1)
)
(same-as symbol of piano1 in sect-a) ((a b c) (e f g))
(same-as symbol of piano2 in sect-a) ((g f e) (c b a))
(same-as symbol of piano3 in sect-a) ((b c d) (f g h))
(same-as duration of piano1 in sect-a) (1/16. 1/8.)
(same-as duration of piano2 in sect-a) (1/8. 1/16.)
(same-as duration of piano3 in sect-a) (1/16. 1/8.)
Whole motives as section defaults
<select reset scom>
(def-motive test
length '(1/32)
symbol '(a)
velocity '(10)
duration '(1/32)
)
(def-section sect-a
default
motive test
piano
symbol '(-a -b c)
bass
symbol '(e f g)
)
(same-as symbol of piano in sect-a) (-a -b c)
(same-as length of piano in sect-a) (1/32)
(same-as symbol of bass in sect-a) (e f g)
(same-as velocity of bass in sect-a) (10)
Or using motives as defaults
(def-section sect-a
default
motive (def-motive theme
length '((1/16 1/8))
symbol '((a b c) (e f g))
velocity '(10 20 30)
duration '(1/16. 1/8.))
zone '(1/1 2/1)
piano
symbol '(-a -b c)
bass
symbol '(e f g)
)
Mixing whole motives and motive classes
If you need to connect motives differently, use the combination of connect and single motive definitions. Here 3 motives define material for 3 zones, but the velocity uses only a single list of values from the first motive.
(def-section sect-a
bass
motive (list more1 more2 more3)
velocity (motive name1)
)
(same-as symbol of bass in sect-a) ((a b c) (a b c) (a b c))
(same-as velocity of bass in sect-a) (10 20 30)
Motives with Zones and Tonalities
(def-section sect-a
default
motive (def-motive theme
tonality (activate-tonality (augmented2 c 4) (augmented2 g 4))
zone '(1/1 2/1 3/1)
length '((1/16 1/8))
symbol '((a b c) (e f g))
velocity '(10 20 30)
duration '(1/16. 1/8.))
piano2
motive (rev theme)
piano3
motive (tran theme 1)
)
Motive Operations
There are some predefined motive operations which replicate the most common symbol processors. A mechanism for applying any symbol or vector processor to motives is further provided.
(setq new (++ more1 (>> more1 '-1/16) (>> more1 '1/16)))
(motive new groove)
(motive new velocity)
(>> (++ more1 more2) '1/16)
Stretching
(setq new (** name1 1.5)) ; stretches both note lengths and durations
(motive name1 length) (1/16 1/8)
(motive name1 duration) (1/16. 1/8.)
(motive new length) (3/32 3/16)
(motive new duration) (9/64 9/32)
Transposing
(setq new (tran more1 1))
(motive more1 symbol) (a b c)
(motive new symbol) (b c d)
Inverting
(setq new (inv more1 'a))
(motive more1 symbol) (a b c)
(motive new symbol) (a -b -c)
Reversing
(setq new (rev more1))
(motive more1 symbol) (a b c)
(motive new symbol) (c b a)
(motive more1 velocity) (10 20 30)
(motive new velocity) (30 20 10)
Legatoing
(setq new (leg more1 10))
(motive more1 duration) (1/16. 1/8.)
(motive new duration) (15/16 15/8)
Zoning
(def-section sect-a
piano
motive (list more1 more2 more3)
zone (zone more1 more2 more3)
)
(same-as zone of piano in sect-a) (3/16 3/16 3/16)
(same-as length of piano in sect-a) ((1/16 1/8) (1/16 1/8) (1/16 1/8))
More Motive Operations: app & com
app: Applying Function to Motives
Examples:
Transposing motive
(setq new (app name1 'symbol '(symbol-transpose 1 x)))
(motive new symbol)
Changing motive's length
(setq new (app name1 'length '(change-length :times 1.5 x :ratio)))
(motive name1 length) (1/16 1/8)
(motive new length) (3/32 3/16)
Scrolling lengths
(setq new (app name1 'length '(symbol-scroll 1 x)))
(motive name1 length) (1/16 1/8)
(motive new length) (1/8 1/16)
Making motive play legato (each note plays 5 times longer)
(setq new (app name1 'duration '(change-length :times 5 x :ratio)))
(motive name1 duration)
(motive new duration)
com: Combining Motives
com makes a duplicate of the motive and enables to change one or more classes while doing that. Here symbol-mix is applied to motive name1 and name2 symbols and the result is combined with other motive classes from more1.
Operations can be performed within sections. Here is a summary of different ways to connect motives to sections and instruments.
(def-section sect-a
piano1 ; motive goes through zones
motive name1
piano2 ; motive restarts at each zone
motive (list name1)
piano3 ; uses a motive in each zone
motive (list more1 more2 more3)
piano4 ; motive goes through zones
motive (rev more1)
piano5 ; motive restarts at each zone
motive (list (rev more1))
piano6 ; uses a motive in each zone
motive (list (rev more1) (rev more1) (rev more1))
)
(same-as symbol of piano1 in sect-a) (a b c)
(same-as symbol of piano2 in sect-a) ((a b c))
(same-as symbol of piano3 in sect-a) ((a b c) (a b c) (a b c))
(same-as symbol of piano4 in sect-a) (c b a)
(same-as symbol of piano5 in sect-a) ((c b a))
(same-as symbol of piano6 in sect-a) ((c b a) (c b a) (c b a))
All other motive classes have the same structure, naturally.
Programming Motive Methods
New motive methods (functions that operate only with motives) are easy to define with defmethod. Use mlength, msymbol etc to refer to the same source motive, and use symbol and vector processors for required operation. The idea here is to make a new motive by copying the source elements and process them. Notice the test is-flat. This is needed since the motive can contain both single zone material or multiple zone material. If it is a multizone then each sublist must be processed with mapcar.
(defmethod mymet ((source motive) amount)
(make-instance 'motive
:symbol (msymbol source) ; this copies directly
:length (if (is-flat (mlength source)) ; this changes
(mapcar #'(lambda (x) (change-length :times amount x :ratio))
(mlength source)))
:velocity (mvelocity source)
:channel (mchannel source)
:program (mprogram source)
:controller (mcontroller source)
:duration (mduration source)
:groove (mgroove source)
:tuning (mtuning source)
:zone (mzone source)
:tonality (mtonality source)))
(setq new (mymet more1 10))
(motive more1 length)
(motive new length)
Multiple Operations
Programmable methods make it possible to wrap several functions to process multiple classes at once. For example, it is now easy to create methods which filter symbols, amplify velocities, and process grooves at the same time for the whole motive. The method is then applicable to all motives.
(mapcar #'(lambda (x) (change-length :times amount x :ratio))
(mduration source)))
:tuning (mtuning source)
:groove (mgroove source)
:zone (mzone source)
:tonality (mtonality source)))
(def-motive test
length '((1/16 1/8))
symbol '((a b c) (e f g) (a b c))
velocity '(10 20 30)
duration '(1/16. 1/8.)
)
(setq new (newmet test 10))
(motive new symbol) ((= b c) (e f g) (= b c))
Naming Conventions
There are some differences in naming conventions here.
* Motive method call starts always with the motive name, and then the parameters follow.
* Motive method names should be one-part name, which are easy to memorize. This way methods are also easier to recognize from the usual functions and macros.